﻿using GN.Pay.Utils;
using GN.Pay.Utils.Security;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace GN.Pay.TradeChannel.AliPay.Request
{
    /// <summary>
    /// 服务请求
    /// </summary>
    [Serializable]
    abstract class AServiceRequest : AService
    {
        /// <summary>
        /// 获取服务
        /// </summary>
        public abstract string Service { get; }

        /// <summary>
        /// 参数编码字符集 商户网站使用的编码格式，如utf-8、gbk、gb2312等。
        /// </summary>
        public string _Input_Charset { get; set; }

        /// <summary>
        /// 签名方式 DSA、RSA、MD5三个值可选，必须大写。
        /// </summary>
        public string Sign_Type { get; set; }

        /// <summary>
        /// 签名
        /// </summary>
        public string Sign { get; set; }

        /// <summary>
        /// 合作者身份ID 签约的支付宝账号对应的支付宝唯一用户号。 以2088开头的16位纯数字组成。不可空
        /// </summary>
        public string Partner { get; set; }

        /// <summary>
        /// 生成签名字典
        /// </summary>
        /// <param name="removeKeys">需移除的参数，即不能参与签名的参数</param>
        /// <returns></returns>
        protected SignDictionary BuildSignDictionary(ITradeChannel channel,
            AliPayConfigure config, params string[] removeKeys)
        {
            this.Sign_Type = "RSA";
            var dic = this.GetSignDictionary(StringComparer.InvariantCultureIgnoreCase);
            Dictionary<string, string> removeItems = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
            if (removeKeys != null)
            {
                foreach (var key in removeKeys)
                {
                    string value;
                    if (key != null && dic.TryGetValue(key, out value))
                    {
                        dic.Remove(key);
                        removeItems[key] = value;
                    }
                }
            }
            string content = dic.UrlLinkString(k =>
            {
                return k.ToLower();
            }, null);
            if (string.IsNullOrWhiteSpace(content))
            {
                channel.ThrowChannelValidationException("待签名内容为null或空白字符");
            }
            this.Sign = RsaFromPkcs8Utils.Sign(content, config.ConfigureInfo.PrivateKey, config.Encoding);
            if (removeItems.Count > 0)
            {
                foreach (var item in removeItems)
                {
                    dic[item.Key] = item.Value;
                }
            }
            dic["Sign"] = Sign;
            return dic;
        }

        /// <summary>
        /// 生成签名参数
        /// </summary>
        /// <param name="removeKeys">需移除的参数，即不能参与签名的参数</param>
        /// <returns></returns>
        protected string BuildSignUrlLinkParam(ITradeChannel channel,
            AliPayConfigure config, params string[] removeKeys)
        {
            var dic = this.BuildSignDictionary(channel, config, removeKeys);
            var param = dic.UrlLinkString(k =>
                {
                    return k.ToLower();
                }, v =>
                {
                    return HttpUtility.UrlEncode(v, config.Encoding);
                });
            dic.Clear();
            return param;
        }
    }
}
